﻿using FluentAssertions;
using Microsoft.EntityFrameworkCore;
using NewRetail.Application.Components.PrintTask.Entity;
using NewRetail.Application.Components.Warehouse.Entity;
using NewRetail.Application.Core;
using NewRetail.Application.Core.Entity;
using System;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Uow;

namespace NewRetail.Application.Components.Warehouse
{
    public class ApproveOrRevoke : EntityDto
    {
        public bool? isAuditing { get; set; }
        public int operatorId { get; set; }
        public string receiptNo { get; set; }
        public string remark { get; set; }
        #region add by cl 20221027
        public bool isAutoPrint { get; set; } = false;
        #endregion
    }

    public class ReceiptsHelper : MyApplicationService, ITransientDependency
    {
        private readonly IRepository<CheckStock> checkStocks;
        public ReceiptsHelper(IRepository<CheckStock> checkStocks)
        {
            this.checkStocks = checkStocks;
        }

        /// <summary>
        /// 审批
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="dto"></param>
        /// <param name="onReceiptChanged"></param>
        /// <returns></returns>
        public async Task<T[]> ApproveOrRevoke<T>(ApproveOrRevoke dto, Func<DbContext, T, Task> onReceiptChanged) where T : BaseEntity, IReceiptEntity
        {
            dto.Should().NotBeNull();
            dto.receiptNo.Should().NotBeNullOrEmpty();
            dto.isAuditing.Should().NotBeNull("设置审批状态");
            onReceiptChanged.Should().NotBeNull();

            using var uow = this.UnitOfWorkManager.Begin(requiresNew: true, isTransactional: true);

            var db = await checkStocks.GetDbContextAsync();

            try
            {
                var items = await db.Set<T>().AsTracking()
                    .Where(x => x.receiptNo == dto.receiptNo)
                    .OrderBy(x => x.addTime).MaxTake().ToArrayAsync();

                if (!items.Any())
                {
                    throw new UserFriendlyException("需要审批的票据不存在");
                }

                foreach (var m in items)
                {
                    if (m.isAuditing == dto.isAuditing.Value)
                    {
                        throw new UserFriendlyException("审批状态无需更改");
                    }
                    
                    m.isAuditing = dto.isAuditing.Value;
                    //m.remark = dto.remark;
                    m.operateUserID = dto.operatorId;
                    m.operateTime = this.Clock.Now;

                    this.EntityHelper.SetUpdationInfo(m);

                    await onReceiptChanged.Invoke(db, m);
                }
                #region 审核完成需要设置是否自动打印
                if(typeof(T).Name == "InOutWarehousing")
                {
                    if (dto.isAutoPrint)
                    {
                        //自动打印需要加入打印任务表
                        var printTask = new PrintTaskEntity()
                        {
                            receiptNo = dto.receiptNo,
                            receiptDate = items.FirstOrDefault().receiptDate,
                            printTag = 0,
                            printNo = "P0"
                        };
                        this.EntityHelper.InitEntity(printTask);
                        db.Set<PrintTaskEntity>().Add(printTask);
                    }
                }
                #endregion
                await db.SaveChangesAsync();

                await uow.CompleteAsync();

                return items;
            }
            catch(Exception e)
            {
                await uow.RollbackAsync();
                throw e;
            }
        }
    }
}
